package com.sky.Aop;

import com.sky.anno.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class AutoFillAspect {
    //

    @Before("@annotation(com.sky.anno.AutoFill)")
    public void autoFill(JoinPoint joinPoint) {
        //joinPoint 被增强的原始方法
        //1.基于joinPoint获取原始方法对象形式
        Signature signature = joinPoint.getSignature();
        //向下转型
        MethodSignature methodSignature = (MethodSignature) signature;
        //获取被拦截的方法对象
        Method method = methodSignature.getMethod();
        //2.解析方法上注解
        //获取注解对象
        AutoFill annotation = method.getAnnotation(AutoFill.class);
        //获取注解中定义的操作类型
        OperationType operationType = annotation.value();

        //3.获取当前被拦截方法参数值
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            log.info("当前被拦截方法没有参数，无法自动填充");
            return;
        }
        Object arg = args[0];
        Long currentId = BaseContext.getCurrentId();
        LocalDateTime now = LocalDateTime.now();

        if(operationType==OperationType.INSERT){
            try{
                /*
                反射执行
                先获取字节码
                通过字节码获取方法
                再反射执行
                 */
                log.info("自动填充新增操作");
                arg.getClass().getDeclaredMethod("setUpdateUser",Long.class).invoke(arg,currentId);
                arg.getClass().getDeclaredMethod("setUpdateTime",LocalDateTime.class).invoke(arg,now);
                arg.getClass().getDeclaredMethod("setCreateUser",Long.class).invoke(arg,currentId);
                arg.getClass().getDeclaredMethod("setCreateTime",LocalDateTime.class).invoke(arg,now);

            }catch (Exception e){
                log.info("自动填充失败");
                e.printStackTrace();
            }
        }else{
            try{
                log.info("自动填充更新操作");
                arg.getClass().getDeclaredMethod("setUpdateUser",Long.class).invoke(arg,currentId);
                arg.getClass().getDeclaredMethod("setUpdateTime",LocalDateTime.class).invoke(arg,now);
            }catch (Exception e){
                log.info("自动填充失败");
                e.printStackTrace();
            }

        }
    }
}
